﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Common.Utilities.Excel.Xml;

namespace Common.Utilities.Excel.Export
{
    public class Formula
    {
        /// <summary>
        /// 公式类型
        /// </summary>
        public FormulaTypeEnums Type { get; set; }
        /// <summary>
        /// 公式所作用的目标, 配置方法为: WorksheetID.AreaID.ColumnID or WorksheetID.AreaID.CellID
        /// </summary>
        public string Target { get; set; }
        /// <summary>
        /// 公式文本, 其中包含若干个需要被格式化的内容, 有多少个操作数, 就有多少个内容需要被格式化, eg: {0}+{1}
        /// </summary>
        public string FormulaText { get; set; }
        /// <summary>
        /// 列公式文本, 当Type == FormulaTypeEnums.RowAndColumn时才有效, 当DataRow[RowsField]取到的值为空时, 就会使用这个公式文本
        /// </summary>
        public string ColumnFormulaText { get; set; }
        /// <summary>
        /// 操作数, 除Type == FormulaTypeEnums.Row 且操作数为本行的参数时需要直接设置为ColumnID外, 其他情况都需要设置为WorksheetID.AreaID.ColumnID或WorksheetID.AreaID.CellID
        /// </summary>
        public string Operation { get; set; }
        /// <summary>
        /// 列公式文本, 当Type == FormulaTypeEnums.RowAndColumn时才有效, 当DataRow[RowsField]取到的值为空时, 就会使用这个操作数串
        /// </summary>
        public string ColumnOperation { get; set; }
        /// <summary>
        /// 指定从DataRow中的哪个Field获取此行的子行, 用于构成Type == FormulaTypeEnums.Column或Type == FormulaTypeEnums.RowAndColumn的公式参数
        /// </summary>
        public string RowsField { get; set; }

        /// <summary>
        /// 过滤的字符
        /// </summary>
        public string FactorValue { get; set; }

        /// <summary>
        /// 当Type == FormulaTypeEnums.RowAndColumn或Type == FormulaTypeEnums.Column时, 设置公式的优先级为行优先还是列优先
        /// 例如当配置FormulaText="{0}+{1}"(或ColumnFormulaText="({0}*{1})"), DataRow[RowsField] == "2,3,4" 时, 操作数转换为列名分别为 B 和 C 时
        /// ColumnPriority == ColumnPriorityEnums.Row将会生成公式 (B2*C2)+(B3*C3)+(B4*C4)
        /// ColumnPriority == ColumnPriorityEnums.Column将会生成公式 B2+B3+B4*C2+C3+C4
        /// 默认为Row
        /// </summary>
        public ColumnPriorityEnums ColumnPriority { get; set; }

        public Formula(XmlNode formulaNode)
        {
            string type = XmlUtility.getNodeAttributeStringValue(formulaNode, "type");
            if (!string.IsNullOrEmpty(type))
                Type = GetFormulaType(formulaNode);
            else
                throw new Exception("需要属性\"type\"没有提供");
            Target = XmlUtility.getNodeAttributeStringValue(formulaNode, "target");
            FormulaText = XmlUtility.getNodeAttributeStringValue(formulaNode, "formulatext");
            Operation = XmlUtility.getNodeAttributeStringValue(formulaNode, "operation");
            RowsField = XmlUtility.getNodeAttributeStringValue(formulaNode, "rowsfield");
            FactorValue = XmlUtility.getNodeAttributeStringValue(formulaNode, "FactorValue");
            ColumnFormulaText = XmlUtility.getNodeAttributeStringValue(formulaNode, "colformulatext");
            ColumnOperation = XmlUtility.getNodeAttributeStringValue(formulaNode, "coloperation");
            ColumnPriority = GetColumnPriority(formulaNode);
        }

        public FormulaTypeEnums GetFormulaType(XmlNode formulaNode)
        {
            switch (XmlUtility.getNodeAttributeStringValue(formulaNode, "type", "").ToLower())
            {
                case "column":
                    return FormulaTypeEnums.Column;
                case "row" :
                    return FormulaTypeEnums.Row;
                case "rowandcolumn":
                    return FormulaTypeEnums.RowAndColumn;
                default:
                case "cell":
                    return FormulaTypeEnums.Cell;
            }
        }

        public ColumnPriorityEnums GetColumnPriority(XmlNode formulaNode)
        {
            switch (XmlUtility.getNodeAttributeStringValue(formulaNode, "columnpriority", "").ToLower())
            {
                case "row":
                default:
                    return ColumnPriorityEnums.Row;
                case "column":
                    return ColumnPriorityEnums.Column;
            }
        }
    }
}
